package br.ufrj.dcc.trabxml.util;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.ConnectException;
import java.rmi.RemoteException;

import javax.xml.rpc.ServiceException;

import exist.Admin;
import exist.AdminServiceLocator;
import exist.Query;
import exist.QueryResponse;
import exist.QueryServiceLocator;

/**
 *
 * @author Artur
 */
public class EXistConnection {
    
    private String user;
    
    private String passwd;
    
    private String host;
    
    private int port;
    
    private String dbname;
    
    private Query query = null;
    
    private Admin admin = null;
    
    private String sessionID = null;
    
    public EXistConnection() {
        super();
        this.user = Properties.instance.getProperty("dbuser");
        this.passwd = Properties.instance.getProperty("dbpassword");
        this.host = Properties.instance.getProperty("dbhost");
        this.port = Integer.valueOf(Properties.instance.getProperty("dbport"));
        this.setDbname(Properties.instance.getProperty("dbname"));
    }    
    
    public EXistConnection(String usuario,String senha,String host,int porta, String dbname) {
        this();
        this.user = usuario;
        this.passwd = senha;
        this.host = host;
        this.port = porta;
        this.setDbname(dbname);        
    }
    
    public boolean connected() {
        return sessionID != null;
    }
    
    public synchronized void connect(String usuario, String senha, String host, int porta)  throws MalformedURLException,ServiceException, RemoteException{
        this.user = usuario;
        this.passwd = senha;
        this.host = host;
        this.port = porta;
        connect();
    }
    
    public synchronized void connect()  throws MalformedURLException,ServiceException, RemoteException{
        if (!connected()) {
            QueryServiceLocator locator = new QueryServiceLocator();
            URL url = new URL("http://"+host+":"+port+"/exist/services/Query");
            query = locator.getQuery(url);
            AdminServiceLocator adminLocator = new AdminServiceLocator();
            url = new URL("http://"+host+":"+port+"/exist/services/Admin");
            admin = adminLocator.getAdmin(url);
            sessionID = admin.connect(user,passwd);
        }
    }
    
    public synchronized void disconnect() throws RemoteException{
        if (connected()) {
            admin.disconnect(sessionID);
            query = null;
            admin = null;
            sessionID = null;
        }
    }
    
    public String gainFile(String nomearquivo) throws RemoteException, UnsupportedEncodingException {
        return gainFile(nomearquivo,"UTF-8");
    }
    
    public QueryResponse queryXPath(String xpath) throws RemoteException {
        if (!connected()) {
            throw new ConnectException("You must be connected.");
        }
        return query.query(sessionID, xpath);
    }
    
    public String gainFile(String nomearquivo, String charset) throws RemoteException, UnsupportedEncodingException {
        if (!connected()) {
            throw new ConnectException("You must be connected.");
        }
        byte[] data = new byte[0];
        data = query.getResourceData(sessionID, "/"+getDbname()+nomearquivo,
                true, false, false);
        String xml = new String(data, charset);
        return xml;
    }
    
    public void storeFile(String file, String xml) throws ConnectException, UnsupportedEncodingException, RemoteException {
        storeFile(file,xml,"UTF-8");
    }     
    
    public void storeFile(String file, String xml, String charset) throws ConnectException, UnsupportedEncodingException, RemoteException {
        if (!connected()) {
            throw new ConnectException("You must be connected.");
        }
        admin.store(sessionID,xml.getBytes(charset),charset,"/"+getDbname()+file,true);
        admin.unlockResource(sessionID,"/"+getDbname()+file);
    }    
    
    public boolean containsFile(String nomearquivo) {
        try {
            gainFile(nomearquivo);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    public void deleteFile(String nomearquivo) throws ConnectException, UnsupportedEncodingException, RemoteException {
        if (!connected()) {
            throw new ConnectException("You must be connected.");
        }
        admin.removeDocument(sessionID, "/"+getDbname()+nomearquivo);
    }

    public void setDbname(String dbname) {
        this.dbname = dbname;
    }

    public String getDbname() {
        return dbname;
    }

}

